﻿using Tpl.Domain.Repository;
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;
using Tpl.Ef.Pe;

namespace Tpl.EF.Pe.Repository
{
    public class GenericRepository<TEntity, Tkey> : IAsyncRepository<TEntity, Tkey> where TEntity : class
    {
        protected readonly LibraryDbContext _dbContext;

        public GenericRepository(LibraryDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        ~GenericRepository()
        {
            _dbContext?.Dispose();
        }

        public virtual IQueryable<TEntity> All()
        {
            return All(null);
        }

        public virtual IQueryable<TEntity> All(string[] propertiesToInclude)
        {
            var query = _dbContext.Set<TEntity>().AsNoTracking();

            if (propertiesToInclude != null)
            {
                foreach (var property in propertiesToInclude.Where(p => !string.IsNullOrWhiteSpace(p)))
                {
                    query = query.Include(property);
                }
            }

            return query;
        }

        public int Delete(bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public int Delete(TEntity entity, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public int Delete(IEnumerable<TEntity> entities, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public int Delete(List<TEntity> entities, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public int Delete(Expression<Func<TEntity, bool>> predicate, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public int Delete(bool saveChanges = true, params object[] KeyValues)
        {
            throw new NotImplementedException();
        }

        public Task<int> DeleteAsync(bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public Task<int> DeleteAsync(TEntity entity, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public Task<int> DeleteAsync(IEnumerable<TEntity> entities, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public Task<int> DeleteAsync(List<TEntity> entities, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public Task<int> DeleteAsync(bool saveChanges = true, params object[] KeyValues)
        {
            throw new NotImplementedException();
        }

        public int Insert(TEntity entity, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public int Insert(IEnumerable<TEntity> entities, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public int Insert(List<TEntity> entities, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public Task<int> InsertAsync(TEntity entity, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public Task<int> InsertAsync(IEnumerable<TEntity> entities, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public Task<int> InsertAsync(List<TEntity> entities, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public int Update(TEntity entity, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public int Update(IEnumerable<TEntity> entities, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public int Update(List<TEntity> entities, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public int Update(Expression<Func<TEntity, bool>> predicate, TEntity entity, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public Task<int> UpdateAsync(TEntity entity, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public Task<int> UpdateAsync(IEnumerable<TEntity> entities, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public Task<int> UpdateAsync(List<TEntity> entities, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public Task<int> UpdateAsync(Expression<Func<TEntity, bool>> predicate, TEntity entity, bool saveChanges = true)
        {
            throw new NotImplementedException();
        }

        public virtual IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> filter)
        {
            return Where(filter, null);
        }

        public virtual IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> filter, string[] propertiesToInclude)
        {
            var query = _dbContext.Set<TEntity>().AsNoTracking();

            if (filter != null)
            {
                query = query.Where(filter);
            }

            if (propertiesToInclude != null)
            {
                foreach (var property in propertiesToInclude.Where(p => !string.IsNullOrWhiteSpace(p)))
                {
                    query = query.Include(property);
                }
            }

            return query;
        }
    }
}
